home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacFormat 1997 February
/
macformat-047.iso
/
Shareware Plus
/
Developers
/
The Gray Council 1.2.1
/
source
/
Core
/
GrayCouncil.h
< prev
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
UTF-8
Wrap
Text File
|
1996-11-07
|
54.8 KB
|
1,537 lines
|
[
TEXT/CWIE
]
//
// The Gray Council
// Copyright ©1996 by Trygve Isaacson. All Rights Reserved.
//
// Before using any of the Gray Council source code, read and
// follow the licensing info in the accompanying documentation
// or contact:
// <trygve@bombaydigital.com>
// <http://www.bombaydigital.com>
//
// Also check the web site above to make sure you have the latest version!
//
// The Gray Council provides a set of standard C++ classes that implement
// the standard Apple Grayscale Appearance. The core classes do not
// require any other code such as a particular class framework.
// There are separate files provided that plug The Gray Council core
// into class frameworks.
//
// Classes defined below:
// AGAObject -- abstract base class for most others
// MExclusiveObject -- mixin class for mutual exclusivity (e.g. radio)
// AGATextStyle -- text style attributes container
// AGADrawingEnvironment -- stack-based save/restore class for drawing attributes
// AGAStaticText -- simple string object
// AGAPushButton -- push button with auto default outline capability
// AGACheckBox -- check box with mixed state capability
// AGAOffscreenImage -- class for storing and drawing an offscreen pixmap
// AGARadioButton -- radio button with mixed state capability
// MIconButtonObject -- mixin class for icon buttons
// AGAIconPushButton -- AGAPushButton subclass for icon push buttons
// AGAIconCheckBox -- AGACheckBox subclass for on/off icon buttons
// AGAIconRadioButton -- AGARadioButton subclass for mutually exclusive
// on/off icon buttons
// AGATrackingIndicator -- abstract superclass for scroll bar and slider
// AGAScrollBar -- scroll bar with 32-bit values, live tracking, and
// proportional indicator capabilities
// AGASlider -- slider with pointy or rectangular indicator, optional
// labels, live tracking, proportional indicator capabilities
// AGAPopupMenu -- popup menu with optional title
// AGACustomPopupMenuSizer -- stack-based class to make PopupMenuSelect use custom font/size
// AGALittleArrows -- little up/down arrows with notification
// AGADisclosureTriangle -- disclosure triangle with animation
// AGAProgressIndicator -- determinate or indeterminate progress gauge
// with moving determinate origin capability
// AGASeparator -- separator line with automatic directionality
// AGAGroupBox -- primary or secondary group box with optional title or
// room for external title or control
// AGATabPanel -- folder tabs for switching panels
// GDIterator -- stack-based class for multi-screen drawing
//
#pragma once
#ifndef __GRAYCOUNCIL__
#define __GRAYCOUNCIL__
#define kGrayCouncilCopyright "\pThe Gray Council ©1996 by Trygve Isaacson. All Rights Reserved."
#include <Errors.h>
#include <Events.h>
#include <Fonts.h>
#include <Gestalt.h>
#include <Icons.h>
#include <Menus.h>
#include <OSUtils.h>
#include <Quickdraw.h>
#include <Resources.h>
#include <TextEdit.h>
#include <TextUtils.h>
#include <Types.h>
#include <Windows.h>
//
// You must call InitGrayCouncil after initializing the Toolbox
// and before instantiating any GrayCouncil objects. This routine
// is called automatically if you call the framework-specific
// initializer. If it returns an error, you should quit. The only
// current error situation of this is an out-of-memory condition
// during initialization of the offscreen images.
//
extern OSErr InitGrayCouncil();
#pragma mark AGAObject
//
// AGAObject ---------------------------------------------------------------
//
// All of the visual GrayCouncil objects inherit from AGAObject.
//
// In general, all you have to do with any AGAObject is instantiate it,
// and then call its DrawObject() and TrackMouse() functions when needed.
// When calling the drawing and mouse tracking functions (and this includes
// functions where you set an attribute with redraw set to true), you must
// ensure that the GrafPort and coordinate system are correct prior to the
// call.
//
// Public functions:
// - AGAObject. You supply its coordinate boundary.
// - GetObjectBounds. Returns its coordinate boundary.
// - SetObjectBounds. Call this to change its coordinate boundary.
// - DrawObject. Draws the object. Assumes current port, pen normal.
// - ContainsMouse. Returns true if specified mouse would hit it.
// - TrackMouse. Handles a mouse click. Returns true if hit did something.
// - SetEnable. Enables or disables it.
// - SetBackgroundColors. Sets the colors the object will use when erasing its background.
//
// You can #define AGA_SUPERCLASS to be TObject or whatever
// if you prefer to have the AGA stuff not be its own root
// class hierarchy.
//
class AGAObject
#ifdef AGA_SUPERCLASS
: public AGA_SUPERCLASS
#endif // AGA_SUPERCLASS
{
public:
AGAObject(Rect* bounds);
virtual ~AGAObject();
virtual void GetObjectBounds(Rect* bounds);
virtual void SetObjectBounds(Rect* bounds, Boolean redraw);
virtual void DrawObject();
virtual Boolean ContainsMouse(Point mouseLocation);
virtual Boolean TrackMouse(Point mouseLocation);
virtual void SetEnable(Boolean isEnabled, Boolean redraw);
virtual void SetBackgroundColors(RGBColor* enabledColor, RGBColor* disabledColor);
virtual SInt32 GetValue();
virtual void SetValue(SInt32 newValue, Boolean redraw);
enum { kRedraw = true, kDontRedraw = false };
enum { kEnabled = true, kDisabled = false };
enum { kPressed = true, kNotPressed = false };
enum { kFrameInside = true, kFrameOutside = false };
enum { kIsDefault = true, kIsNotDefault = false };
enum { kAutomaticState = true, kNoAutomaticState = false };
enum { kLiveTracking = true, kNoLiveTracking = false };
enum { kProportional = true, kNotProportional = false };
enum { kHorizontal = true, kVertical = false };
enum { kTrackingIn = true, kTrackingOut = false };
protected:
// HitTest and SetTrackingState are called repeatedly by the default
// mouse tracker.
virtual Boolean HitTest(Point mouseLocation);
virtual void SetTrackingState(Boolean isIn);
virtual void ApplyBackgroundColor();
Rect mBounds;
Boolean mEnabled;
RGBColor mEnabledBackgroundColor;
RGBColor mDisabledBackgroundColor;
};
#pragma mark MExclusiveObject
//
// MExclusiveObject ---------------------------------------------------------------
//
// MExclusiveObject is a mixin class for automatically keeping several
// objects in a group mutually exclusive. The radio button class below
// uses this to allow automatic radio button group behavior. MExclusiveObject
// maintains knowledge of "groups" of objects. When one member of the group is
// "hit", the other members of the group are sent the TurnOff() message. To
// identify each object uniquely, the object has a pair of 32-bit identifiers.
// Typically these can set to the group's ID and GrafPtr. This allows having
// multiple windows that use the same group IDs. If you set the IDs to kNoGroupID,
// then this automatic maintenance is bypassed.
// The MacApp and PowerPlant adapter classes do not use this facility, because
// these frameworks provide their own radio button group management.
//
class MExclusiveObject
{
public:
MExclusiveObject(UInt32 groupIDPart1, UInt32 groupIDPart2);
virtual ~MExclusiveObject();
virtual void SetGroupID(UInt32 groupIDPart1, UInt32 groupIDPart2);
virtual void TurnOff();
UInt32 mGroupIDPart1;
UInt32 mGroupIDPart2;
};
const UInt32 kNoGroupID = 0xFFFFFFFF;
#pragma mark AGATextStyle
//
// AGATextStyle ---------------------------------------------------------------
//
// Many of the controls can have their text style specified. AGATextStyle
// is used for this. It defines the font, size, and style to be used for
// drawing text.
//
class AGATextStyle
{
public:
AGATextStyle();
AGATextStyle(SInt16 fontNum, SInt16 fontSize, Style fontStyle);
AGATextStyle(StringPtr fontName, SInt16 fontSize, Style fontStyle);
AGATextStyle(const TextStyle& textStyle);
#ifdef __PowerPlant__
AGATextStyle(ResIDT inTextTraitsID); // Note: implementation is in GrayCouncilPP.cpp
#endif // __PowerPlant__
void PrepareForDrawing() const;
SInt16 mFontNum;
SInt16 mFontSize;
Style mFontStyle;
};
// These globals should be used in most cases. You can also roll your own.
extern AGATextStyle gAGAStdSystemStyle; // Typically Chicago 12. Standard.
extern AGATextStyle gAGAStdSmallStyle; // Typically Geneva 10. Slider labels.
extern AGATextStyle gAGAStdBoldSmallStyle; // Typically Geneva 10 bold. Small tab panels.
extern AGATextStyle gAGAExtraSmallStyle; // Typically Geneva 9. Use where you need a small control.
#pragma mark AGADrawingEnvironment
//
// AGADrawingEnvironment ---------------------------------------------------------------
//
// AGADrawingEnvironment is a stack-based object that saves the existing drawing
// settings upon construction, and restores them upon destruction. It also
// cleanses the pen after saving the existing settings, so that our drawing
// code can assume basic settings are in place.
//
class AGADrawingEnvironment
{
public:
AGADrawingEnvironment();
virtual ~AGADrawingEnvironment();
void SaveEnvironment(); // called by constructor
void RestoreEnvironment(); // called by destructor
void Cleanse(); // called by constructor after saving environment
// sets drawing state to a clean set of values
protected:
PenState mSavedPenState;
RGBColor mSavedForeColor;
RGBColor mSavedBackColor;
SInt16 mSavedFontNum;
SInt16 mSavedFontSize;
Style mSavedFontStyle;
};
#pragma mark AGAStaticText
//
// AGAStaticText ---------------------------------------------------------------
//
// AGAStaticText draws a static text string on a gray background.
//
class AGAStaticText : public AGAObject
{
public:
AGAStaticText(Rect* bounds, const AGATextStyle& textStyle, SInt32 justification);
AGAStaticText(Rect* bounds, const AGATextStyle& textStyle, SInt32 justification, StringPtr title);
AGAStaticText(Rect* bounds, const AGATextStyle& textStyle, SInt32 justification, SInt16 stringListResourceID, SInt16 stringIndex);
virtual ~AGAStaticText();
virtual void DrawObject();
virtual void SetTitle(StringPtr buttonTitle, Boolean redraw);
protected:
SInt32 mJustification;
Str255 mTitle;
AGATextStyle mTextStyle;
};
#pragma mark AGAPushButton
//
// AGAPushButton ---------------------------------------------------------------
//
// AGAPushButton implements the standard AGA pushbutton. It automatically
// draws the default button outline if you set its mIsDefault property
// by calling SetDefault; you specify whether the outline is inside or
// outside the object's mBounds.
//
class AGAPushButton : public AGAObject
{
public:
AGAPushButton(Rect* bounds, const AGATextStyle& textStyle);
AGAPushButton(Rect* bounds, const AGATextStyle& textStyle, StringPtr buttonTitle);
AGAPushButton(Rect* bounds, const AGATextStyle& textStyle, SInt16 stringListResourceID, SInt16 stringIndex);
virtual ~AGAPushButton();
virtual void DrawObject();
virtual void SetTitle(StringPtr buttonTitle, Boolean redraw);
virtual void SetDefault(Boolean isDefault, Boolean frameInside);
virtual Boolean IsDefault();
virtual void DrawButton(Boolean pressed);
protected:
virtual Boolean HitTest(Point mouseLocation);
virtual void SetTrackingState(Boolean isIn);
virtual void DrawButtonNormal(Boolean deep);
virtual void DrawButtonPressed(Boolean deep);
virtual void DrawButtonDisabled(Boolean deep);
virtual void DrawOutlineNormal(Boolean deep);
virtual void DrawOutlineDisabled(Boolean deep);
Boolean mIsDefault; // if true this button gets a default frame
Boolean mFrameInside; // if true the frame is inside mBounds; else outside
Str255 mTitle;
AGATextStyle mTextStyle;
};
#pragma mark AGACheckBox
//
// AGACheckBox ---------------------------------------------------------------
//
// AGACheckBox implements the standard AGA check box. It also supports
// a mixed state that is neither on nor off, which is drawn as a dash.
//
class AGACheckBox : public AGAObject
{
public:
enum { kCheckBoxSize = 12 };
enum { kCheckBoxOff = 0, kCheckBoxOn = 1, kCheckBoxMixed = 2 };
AGACheckBox(Rect* bounds, const AGATextStyle& textStyle, Boolean automaticState);
AGACheckBox(Rect* bounds, const AGATextStyle& textStyle, StringPtr buttonTitle, Boolean automaticState);
AGACheckBox(Rect* bounds, const AGATextStyle& textStyle, SInt16 stringListResourceID, SInt16 stringIndex, Boolean automaticState);
virtual ~AGACheckBox();
virtual void DrawObject();
virtual Boolean TrackMouse(Point mouseLocation);
virtual void SetTitle(StringPtr buttonTitle, Boolean redraw);
virtual SInt32 GetValue();
virtual void SetValue(SInt32 newValue, Boolean redraw);
virtual void DrawButton(Boolean pressed);
protected:
virtual void SetTrackingState(Boolean isIn);
virtual void DrawButtonNormal(Boolean deep);
virtual void DrawButtonPressed(Boolean deep);
virtual void DrawButtonDisabled(Boolean deep);
SInt32 mValue;
Boolean mAutomaticState; // if true, check is toggled on click w/o caller needing to call SetValue
Str255 mTitle;
AGATextStyle mTextStyle;
};
#pragma mark AGAOffscreenImage
//
// AGAOffscreenImage ------------------------------------------------------------
//
// AGAOffscreenImage holds the data needed to blast a clipped region
// of pixel values onto the current port. This is used by the AGARadioButton
// class to avoid the ultra-tedious pixel-by-pixel drawing of the grayscale
// radio button images, and by the tab panel for the tab corners.
//
class AGAOffscreenImage
#ifdef AGA_SUPERCLASS
: public AGA_SUPERCLASS
#endif // AGA_SUPERCLASS
{
public:
AGAOffscreenImage();
virtual ~AGAOffscreenImage();
virtual OSErr CreateImageData(Point imageSize,
SInt8* imageColorIndexes,
RgnHandle clippingRegion,
const RGBColor* outsideColor);
void DrawImage(SInt16 imageHOrigin, SInt16 imageVOrigin); // splats 1 copy of the image
void DrawPattern(Rect* imageRect); // splats multiple copies of the image
protected:
Rect mImageSourceRect; // 0, 0, x, y
PixMapHandle mImagePixMap;
RgnHandle mClippingRegion;
};
#pragma mark AGARadioButton
//
// AGARadioButton ---------------------------------------------------------------
//
// AGARadioButton implements the standard AGA radio button. It also supports
// a mixed state that is neither on nor off, which is drawn as a dash.
// You can also assign an ID pair that will be used to automatically keep
// the radio button mutually exclusive with others with the same ID pair.
// Pass kNoGroupID for the IDs to bypass this. The adapter classes bypass it
// since the frameworks manage radio button groups.
//
class AGARadioButton : public AGAObject, public MExclusiveObject
{
public:
enum { kRadioButtonOff = 0, kRadioButtonOn = 1, kRadioButtonMixed = 2 };
static OSErr AllocateRadioImages();
static void DisposeRadioImages();
AGARadioButton(Rect* bounds, const AGATextStyle& textStyle, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState);
AGARadioButton(Rect* bounds, const AGATextStyle& textStyle, StringPtr buttonTitle, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState);
AGARadioButton(Rect* bounds, const AGATextStyle& textStyle, SInt16 stringListResourceID, SInt16 stringIndex, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState);
virtual ~AGARadioButton();
virtual void DrawObject();
virtual Boolean TrackMouse(Point mouseLocation);
virtual void SetTitle(StringPtr buttonTitle, Boolean redraw);
virtual SInt32 GetValue();
virtual void SetValue(SInt32 newValue, Boolean redraw);
virtual void SetGroupID(UInt32 groupIDPart1, UInt32 groupIDPart2); // MExclusiveObject mixin override
virtual void TurnOff(); // MExclusiveObject mixin override
virtual void DrawButton(Boolean pressed);
protected:
virtual void SetTrackingState(Boolean isIn);
virtual void DrawButtonNormal(Boolean deep);
virtual void DrawButtonPressed(Boolean deep);
virtual void DrawButtonDisabled(Boolean deep);
virtual void CopyImage(UInt32 index);
SInt32 mValue;
Boolean mAutomaticState; // if true, radio is set on click w/o caller needing to call SetValue
UInt32 mGroupID;
Str255 mTitle;
AGATextStyle mTextStyle;
// Drawing the 3D radio button manually is just too damn tedious.
// So we use offscreen PixMap structures and blast them onto the screen.
// The mask (clip) region for the images is a round rectangle.
enum { kRadioImageWidth = 12, kRadioImageHeight = 12 };
enum { kRadioNormalOff, kRadioNormalOn, kRadioNormalMixed,
kRadioPressedOff, kRadioPressedOn, kRadioPressedMixed,
kRadioDisabledOff, kRadioDisabledOn, kRadioDisabledMixed,
kNumRadioImages };
static SInt8 kRadioImageValues[kNumRadioImages]
[kRadioImageHeight]
[kRadioImageWidth];
static AGAOffscreenImage* mgOffscreenRadioImages[kNumRadioImages];
};
#pragma mark MIconButtonObject
//
// MIconButtonObject ---------------------------------------------------------------
//
// MIconButtonObject is a mixin class for the classes that have an
// icon button appearance. There are two different basic visual
// attributes for a button: the frame type and the image type.
//
// The frame type determines what the button edges look like. There
// are 3 different frame types specified by the AGA. The size of
// the button determines which frame type is used, but you can
// force a given type to be used.
// - 40x40 or larger: kLargeFrame (4 pixels shading on each side)
// This is room for a 32x32 'iclx' plus the shading.
// - 22x22 or larger: kSmallFrame (3 pixels shading on each side)
// This is room for a 16x16 'icsx' plus the shading.
// - 16x16 or larger: kMiniFrame (2 pixels shading on each side)
// This is room for a 12x12 'icmx' plus the shading.
// The constant kAutoFrame is used by default. This sets the frame type
// automatically based on the actual button bounds. The dimensions shown
// above are the ideal dimensions shown in the AGA spec.
//
// The image type determines how the actual picture image inside the
// button is drawn. By default the image type is an icon family of size
// based on the button size (according to the frame sizes listed above),
// but you can explicitly set the type, including non-icon-family types.
// In all cases, the image is centered inside the button frame.
// - kAutoIconFamily: 32x32, 16x16, or 12x12 icon rect, derived from
// the button bounds, according to the ideal sizes list above,
// using an icon family.
// - kLargeIcon: 32x32 icon rect ('iclx' size) using an icon family.
// - kSmallIcon: 16x16 icon rect ('icsx' size) using an icon family.
// - kMiniIcon: 12x12 icon rect ('icmx' size) using an icon family.
// - kColorIcon: arbitrary icon rect derived from / using a 'cicn' resource.
// - kPictureIcon: arbitrary icon rect derived from / using a 'PICT' resource.
//
// An icon button has two image resource IDs. Usually these are the same,
// but for some button types you can make them different. For example, if
// you want different icons for on/off when the button is used as a radio
// button or check box, you can set the IDs to different values.
//
// Note that mini icons are a rather rare resource type, and ResEdit 2.x
// doesn't have an editor for them. I think Resorcerer does.
//
class MIconButtonObject
{
public:
enum { kNoIconID = -1 };
enum ButtonFrameType { kAutoFrame, kLargeFrame, kSmallFrame, kMiniFrame };
enum ButtonImageType { kAutoIconFamily, kLargeIcon, kSmallIcon, kMiniIcon, kColorIcon, kPictureIcon };
MIconButtonObject();
MIconButtonObject(SInt16 offIconID, SInt16 onIconID, ButtonFrameType frameType, ButtonImageType imageType);
virtual ~MIconButtonObject();
virtual void SetIconIDs(SInt16 offIconID, SInt16 onIconID);
virtual void SetFrameType(ButtonFrameType frameType);
virtual void SetImageType(ButtonImageType imageType);
virtual void DrawIconButton(Rect* bounds,
Boolean isOn,
Boolean isPressed,
Boolean isEnabled,
Boolean deep);
static ButtonFrameType GetDefaultFrameType(SInt16 buttonWidth);
static ButtonImageType GetDefaultImageType(SInt16 buttonWidth);
protected:
virtual void DrawMiniEdges(Rect* bounds, Boolean isOn, Boolean isPressed, Boolean isEnabled);
virtual void DrawSmallEdges(Rect* bounds, Boolean isOn, Boolean isPressed, Boolean isEnabled);
virtual void DrawLargeEdges(Rect* bounds, Boolean isOn, Boolean isPressed, Boolean isEnabled);
virtual PicHandle GetPictureImage(Point* imageSize, SInt16 pictureResourceID);
virtual CIconHandle GetColorIconImage(Point* imageSize, SInt16 cicnResourceID);
SInt16 mOffIconID;
SInt16 mOnIconID;
ButtonFrameType mFrameType;
ButtonImageType mImageType;
};
#pragma mark AGAIconPushButton
//
// AGAIconPushButton ---------------------------------------------------------------
//
// AGAIconPushButton implements the standard AGA icon button, with
// pushbutton behavior; that is to say, it has no state. This is
// done by subclassing AGAPushButton for tracking, and mixing in
// MIconButtonObject for drawing.
//
class AGAIconPushButton : public AGAPushButton, public MIconButtonObject
{
public:
AGAIconPushButton(Rect* bounds);
AGAIconPushButton(Rect* bounds, SInt16 iconID, ButtonFrameType frameType, ButtonImageType imageType);
virtual ~AGAIconPushButton();
protected:
virtual void DrawButtonNormal(Boolean deep);
virtual void DrawButtonPressed(Boolean deep);
virtual void DrawButtonDisabled(Boolean deep);
};
#pragma mark AGAIconCheckBox
//
// AGAIconCheckBox ---------------------------------------------------------------
//
// AGAIconCheckBox implements the standard AGA icon button, with
// check box behavior; that is to say, it has an on or off state
// that toggles when hit. This is done by subclassing AGACheckBox
// for tracking and state, and mixing in MIconButtonObject for drawing.
//
class AGAIconCheckBox : public AGACheckBox, public MIconButtonObject
{
public:
AGAIconCheckBox(Rect* bounds, Boolean automaticState);
AGAIconCheckBox(Rect* bounds, Boolean automaticState, SInt16 offIconID, SInt16 onIconID, ButtonFrameType frameType, ButtonImageType imageType);
virtual ~AGAIconCheckBox();
protected:
virtual void DrawButtonNormal(Boolean deep);
virtual void DrawButtonPressed(Boolean deep);
virtual void DrawButtonDisabled(Boolean deep);
};
#pragma mark AGAIconRadioButton
//
// AGAIconRadioButton ---------------------------------------------------------------
//
// AGAIconRadioButton implements the standard AGA icon button, with
// radio button behavior; that is to say, it has an on or off state
// that can be automatically made mutually exclusive with other
// buttons in its group. This is done by subclassing AGARadioButton
// for tracking and state, and mixing in MIconButtonObject for drawing.
//
class AGAIconRadioButton : public AGARadioButton, public MIconButtonObject
{
public:
AGAIconRadioButton(Rect* bounds, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState);
AGAIconRadioButton(Rect* bounds, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState, SInt16 offIconID, SInt16 onIconID, ButtonFrameType frameType, ButtonImageType imageType);
virtual ~AGAIconRadioButton();
protected:
virtual void DrawButtonNormal(Boolean deep);
virtual void DrawButtonPressed(Boolean deep);
virtual void DrawButtonDisabled(Boolean deep);
};
#pragma mark AGATrackingIndicator
//
// AGATrackingIndicator ---------------------------------------------------------------
//
// AGATrackingIndicator is the abstract superclass for things like
// sliders and scroll bars that have a moving indicator to reflect
// the object's position. It has a minimum/maximum range, a current
// value, and optionally a page size for proportional indicator
// display. You can turn live tracking on or off; if live tracking
// is off, a "ghost" indicator is dragged and no notification occurs
// until the tracking completes.
//
class AGATrackingIndicator;
// This is the live tracking notification prototype for AGATrackingIndicator.
typedef void (*AGATrackingIndicatorNotifyPtr)(AGATrackingIndicator* theIndicator, SInt32 itsNewValue, void* userData);
class AGATrackingIndicator : public AGAObject
{
public:
AGATrackingIndicator(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue);
AGATrackingIndicator(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, SInt32 pageSize, Boolean liveTracking, Boolean proportional);
virtual ~AGATrackingIndicator();
virtual void InstallNotificationRoutine(AGATrackingIndicatorNotifyPtr notificationRoutine, void* userData);
virtual void SetAttributes(Boolean isHorizontal, Boolean liveTracking, Boolean isProportional);
virtual void SetLiveTracking(Boolean liveTracking);
virtual void DrawObject();
virtual Boolean TrackMouse(Point mouseLocation);
virtual SInt32 GetValue();
virtual void SetValue(SInt32 newValue, Boolean redraw);
virtual void GetRange(SInt32* minimum, SInt32* maximum);
virtual void SetRange(SInt32 newMinimum, SInt32 newMaximum, Boolean redraw);
virtual SInt32 GetPageSize();
virtual void SetPageSize(SInt32 newPageSize, Boolean redraw);
protected:
enum { kNoTrackPress, kPageMinusPress, kArrowMinusPress, kIndicatorPress, kArrowPlusPress, kPagePlusPress };
virtual Boolean TrackPart(Point mouseLocation, SInt32 partHit);
virtual SInt32 TrackTestPart(Point mouseLocation);
virtual Boolean IsValidIndicatorTrackMouse(Point mouseLocation);
virtual SInt32 GetValueFromMouseDelta(SInt32 originalValue, Point originalMouseLocation, Point newMouseLocation);
virtual void SetGhostValue(SInt32 newValue, Boolean redraw);
virtual void DrawBackground();
virtual void DrawIndicatorTrack();
virtual void DrawTrackEnds();
virtual void DrawIndicator();
virtual void RemoveIndicator(SInt32 newValue);
virtual void DrawGhost();
virtual void RemoveGhost(SInt32 newValue);
virtual void NotifyValue();
SInt32 mMinimum;
SInt32 mMaximum;
SInt32 mValue;
SInt32 mPageSize;
SInt32 mGhostValue;
Boolean mLiveTracking;
Boolean mIsProportional;
Boolean mIsHorizontal;
Boolean mIsPressed;
AGATrackingIndicatorNotifyPtr mNotificationRoutine;
void* mUserData;
};
#pragma mark AGAScrollBar
//
// AGAScrollBar ---------------------------------------------------------------
//
// AGAScrollBar implements the standard AGA scroll bar. It also supports
// live indicator tracking and a proportional indicator as options.
//
class AGAScrollBar : public AGATrackingIndicator
{
public:
AGAScrollBar(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue);
AGAScrollBar(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, SInt32 singleStepSize, SInt32 pageStepSize, SInt32 pageSize, Boolean liveTracking, Boolean proportional);
virtual ~AGAScrollBar();
virtual void SetRange(SInt32 newMinimum, SInt32 newMaximum, Boolean redraw);
virtual void SetStepSizes(SInt32 singleStepSize, SInt32 pageStepSize);
virtual void Activate(Boolean activateState, Boolean redraw);
protected:
virtual Boolean TrackPart(Point mouseLocation, SInt32 partHit);
virtual SInt32 TrackTestPart(Point mouseLocation);
virtual Boolean IsValidIndicatorTrackMouse(Point mouseLocation);
virtual SInt32 GetValueFromMouseDelta(SInt32 originalValue, Point originalMouseLocation, Point newMouseLocation);
virtual void DrawIndicatorTrack();
virtual void DrawTrackEnds();
virtual void DrawIndicator();
virtual void RemoveIndicator(SInt32 newValue);
virtual void DrawGhost();
virtual void RemoveGhost(SInt32 newValue);
virtual void TrackDelta(SInt32 partHit);
virtual void DrawArrow(SInt32 arrowPart, Boolean pressed);
enum { kIndicatorPixelInset = 8 };
enum { kArrowSize = 16 };
virtual void GetIndicatorBox(SInt32 value, Rect* indicatorBox);
virtual SInt32 GetIndicatorPixelRange(SInt32* proportionalIndicatorPixels);
virtual void GetIndicatorPixelEnds(SInt32* startPt, SInt32* stopPt);
virtual void GetIndicatorSpan(SInt32 value, SInt32* startPt, SInt32* valuePt, SInt32* stopPt);
SInt32 mSingleStepSize; // amount to delta for arrow tracking
SInt32 mPageStepSize; // amount to delta for page tracking
Boolean mActive; // inactive windows have inactive scroll bars
// These regions are used by RemoveIndicator and RemoveGhost.
// They are tiny but we allocate them statically to avoid
// repeated allocation, which could conceivably fail.
static RgnHandle mgSavedIndicatorClip;
static RgnHandle mgOldIndicatorClip;
static RgnHandle mgNewIndicatorClip;
};
#pragma mark AGASlider
//
// AGASlider ---------------------------------------------------------------
//
// AGASlider implements the standard AGA slider. You specify whether it
// is horizontal or vertical, labeled or unlabeled, rectangular or pointy.
// By default, if you specify a labeled slider, it is pointy; otherwise it
// is rectangular. You can change this by calling SetSliderKind, and you
// can set the labels up after construction by calling the label functions.
// It also supports live indicator tracking and a proportional indicator
// as options.
//
class AGASlider : public AGATrackingIndicator
{
public:
enum SliderKind { kRectSlider, kPointerSlider };
AGASlider(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, const AGATextStyle& textStyle, SInt16 labelsID);
AGASlider(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, const AGATextStyle& textStyle, SInt16 labelsID, SliderKind kind, Boolean liveTracking, Boolean proportional);
virtual ~AGASlider();
virtual void SetSliderKind(SliderKind kind);
virtual void SetLabelsFromResource(SInt16 stringListResourceID);
virtual void SetNumLabels(UInt32 numLabels);
virtual void SetLabel(UInt32 labelIndex, StringPtr itsLabel);
virtual void GetLabel(UInt32 labelIndex, StringPtr itsLabel);
virtual void SetLabelsStyle(const AGATextStyle& textStyle);
virtual void SetJustification(SInt32 justification);
protected:
virtual SInt32 TrackTestPart(Point mouseLocation);
virtual Boolean IsValidIndicatorTrackMouse(Point mouseLocation);
virtual SInt32 GetValueFromMouseDelta(SInt32 originalValue, Point originalMouseLocation, Point newMouseLocation);
virtual void DrawBackground();
virtual void DrawIndicatorTrack();
virtual void DrawIndicator();
virtual void RemoveIndicator(SInt32 newValue);
virtual void DrawGhost();
virtual void RemoveGhost(SInt32 newValue);
enum { kRectIndicatorPixelInset = 6 };
enum { kPointerIndicatorPixelInset = 7 };
enum { kIndicatorWidth = 16 };
enum { kEndGapSize = 5 };
enum { kLabelTickEndInset = 11 };
enum { kLabelTickOffset = 8 };
enum { kLabelPosTextOffset = 14 };
enum { kLabelNegTextOffset = 8 };
enum { kLabelTickLength = 6 };
enum { kGhostIndicator = true, kNormalIndicator = false };
enum { kIncludeBackground = true, kTrackOnly = false };
virtual void GetTrackFrame(Rect* trackFrame, Boolean includeBackground);
virtual void GetIndicatorBox(SInt32 value, Rect* indicatorBox);
virtual SInt32 GetIndicatorPixelRange(SInt32* proportionalIndicatorPixels);
virtual void GetIndicatorPixelEnds(SInt32* startPt, SInt32* stopPt);
virtual void GetIndicatorSpan(SInt32 value, SInt32* startPt, SInt32* valuePt, SInt32* stopPt);
virtual void DrawLabels();
virtual void DrawRectIndicator(Rect* indicatorRect, Boolean isGhost);
virtual void DrawPointerIndicator(Rect* indicatorRect, Boolean isGhost);
virtual void BuildPointerIndicator(Rect* indicatorRect);
virtual void DisposeLabels();
Handle mLabelStringHandles; // an array of StringHandle, may be NULL
SInt32 mJustification;
SliderKind mSliderKind;
AGATextStyle mTextStyle;
// These regions are used by RemoveIndicator and RemoveGhost.
// They are tiny but we allocate them statically to avoid
// repeated allocation, which could conceivably fail.
static RgnHandle mgSavedIndicatorClip;
static RgnHandle mgOldIndicatorClip;
static RgnHandle mgNewIndicatorClip;
};
#pragma mark AGAPopupMenu
//
// AGAPopupMenu ---------------------------------------------------------------
//
// AGAPopupMenu implements the standard AGA pop-up menu. You can specify
// whether the supplied boundary is fixed or whether the pop-up button
// should adapt its width to the width of the associated menu. You can
// also supply a title to be drawn next to the pop-up button.
//
class AGAPopupMenu : public AGAObject
{
public:
enum WidthAdjust { kFixedWidth = -1, kUseMenuWidth = 0, kSystemMDEFAdjustment = 19 };
enum DisposalKind { kDontDispose, kDispose, kRelease };
AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& titleStyle, const AGATextStyle& textStyle, WidthAdjust adjustment);
AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& titleStyle, const AGATextStyle& textStyle, WidthAdjust adjustment, MenuRef itsMenuRef, DisposalKind menuRefDisposalKind);
AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& titleStyle, const AGATextStyle& textStyle, WidthAdjust adjustment, SInt16 itemsStringListID, SInt16 newMenuID);
AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& titleStyle, const AGATextStyle& textStyle, WidthAdjust adjustment, ResType appendResourceType, SInt16 newMenuID);
virtual ~AGAPopupMenu();
virtual void SetMenuRef(MenuRef itsMenuRef, DisposalKind menuRefDisposalKind);
virtual void SetWidthAdjustment(WidthAdjust adjustment);
virtual void DrawObject();
virtual Boolean TrackMouse(Point mouseLocation);
virtual SInt16 GetCurrentItemNo();
virtual void SetCurrentItemNo(SInt16 newItemNo, Boolean redraw);
virtual void GetCurrentItemText(StringPtr itemText);
virtual Boolean SetCurrentItemText(StringPtr itemTextToMatch, Boolean redraw); // returns false if no match found
virtual void SetTitle(StringPtr newTitle, Boolean redraw);
virtual void DrawButton(Boolean pressed);
protected:
virtual void DrawButtonNormal(Boolean deep);
virtual void DrawButtonPressed(Boolean deep);
virtual void DrawButtonDisabled(Boolean deep);
virtual void GetButtonBounds(Rect* buttonBounds);
virtual void GetTitleBounds(Rect* titleBounds);
virtual void DisposeExistingMenuRef();
enum { kPopupArrowSectionWidth = 22 };
SInt16 mMenuID;
MenuRef mMenuRef;
DisposalKind mMenuRefDisposalKind;
SInt16 mCurrentItemNo;
WidthAdjust mWidthAdjust;
AGATextStyle mTitleStyle;
AGATextStyle mTextStyle;
Str255 mTitle;
SInt16 mTitleOffset;
SInt32 mTitleJustification;
};
#pragma mark AGACustomPopupMenuSizer
//
// AGACustomPopupMenuSizer -------------------------------------------------------
//
// AGACustomPopupMenuSizer is a stack-based object that will prepare the
// drawing environment for a custom popup menu font/size. This is a
// low-level toolbox hack capability.
// This is used to wrap calls to PopupMenuSelect and CalcMenuSize.
//
class AGACustomPopupMenuSizer
{
public:
AGACustomPopupMenuSizer(SInt16 fontNum, SInt16 fontSize);
virtual ~AGACustomPopupMenuSizer();
void SaveEnvironment(); // called by constructor
void RestoreEnvironment(); // called by destructor
void InstallCustomEnvironment(); // called by constructor after saving
Boolean mIsCustom;
protected:
SInt16 mSavedFontNum;
SInt16 mSavedFontSize;
SInt16 mCustomFontNum;
SInt16 mCustomFontSize;
};
#pragma mark AGALittleArrows
//
// AGALittleArrows ---------------------------------------------------------------
//
// AGALittleArrows implements the standard AGA little arrows. To respond
// to continuous messages during tracking, you should either install a
// notification routine or subclass and override NotifyDelta. The supplied
// MacApp and PowerPlant classes do this for you.
//
class AGALittleArrows;
// This is the live tracking notification prototype for AGALittleArrows.
typedef void (*AGALittleArrowsNotifyPtr)(AGALittleArrows* theIndicator, SInt32 pressedPart, void* userData);
class AGALittleArrows : public AGAObject
{
public:
enum { kDownArrowPressed = -1, kNoArrowPressed = 0, kUpArrowPressed = 1 };
AGALittleArrows(Rect* bounds);
virtual ~AGALittleArrows();
virtual void InstallNotificationRoutine(AGALittleArrowsNotifyPtr notificationRoutine, void* userData);
virtual void DrawObject();
virtual Boolean TrackMouse(Point mouseLocation);
virtual void DrawButton(SInt32 pressedPart);
protected:
enum { kLittleArrowWidth = 13, kLittleArrowHeight = 12, kLittleArrowTotalHeight = 23 };
virtual Boolean TrackPart(Point mouseLocation, SInt32 partHit);
virtual SInt32 TrackTestPart(Point mouseLocation);
virtual void NotifyDelta(SInt32 partHit);
AGALittleArrowsNotifyPtr mNotificationRoutine;
void* mUserData;
};
#pragma mark AGADisclosureTriangle
//
// AGADisclosureTriangle ---------------------------------------------------------------
//
// AGADisclosureTriangle implements the standard AGA disclosure triangle.
// You can think of it as a check box that is either off (closed) or on
// (disclosed).
//
class AGADisclosureTriangle : public AGAObject
{
public:
enum { kDisclosedState = true, kClosedState = false };
AGADisclosureTriangle(Rect* bounds, Boolean automaticState);
virtual ~AGADisclosureTriangle();
virtual void DrawObject();
virtual Boolean TrackMouse(Point mouseLocation);
virtual Boolean GetState();
virtual void SetState(Boolean isDisclosed, Boolean redraw);
virtual void SetStateAnimate(Boolean isDisclosed);
protected:
virtual void SetTrackingState(Boolean isIn);
enum DTAnimationState { kDTClosed, kDTPressedClosed, kDTIntermediate, kDTPressedDisclosed, kDTDisclosed };
virtual void DrawTriangle(DTAnimationState state);
virtual void EraseBackground();
Boolean mAutomaticState; // if true, triangle is toggled on click w/o caller needing to call SetValue
Boolean mIsDisclosed;
};
#pragma mark AGAProgressIndicator
//
// AGAProgressIndicator ---------------------------------------------------------------
//
// AGAProgressIndicator implements the standard AGA progress indicator.
// It can be determinate (a moving gauge) or indeterminate (a rotating
// barber pole). In addition, it supports a "moving origin", which is
// where, in addition to moving the gauge end point, the gauge start
// point also moves.
//
class AGAProgressIndicator : public AGAObject
{
public:
static OSErr AllocateProgressImages();
static void DisposeProgressImages();
AGAProgressIndicator(Rect* bounds, SInt32 minimum, SInt32 maximum);
virtual ~AGAProgressIndicator();
virtual void DrawObject();
virtual SInt32 GetValue();
virtual void SetValue(SInt32 newValue, Boolean redraw);
virtual void Increment(SInt32 delta, Boolean redraw);
virtual void Animate(); // moves indeterminate indicator by 1
virtual void QuantizedAnimate(); // moves it only if kAnimationDelay has elapsed
virtual void GetRange(SInt32* minimum, SInt32* maximum);
virtual void SetRange(SInt32 newMinimum, SInt32 newMaximum, Boolean redraw);
virtual SInt32 GetOriginValue();
virtual void SetOriginValue(SInt32 newValue, Boolean redraw);
protected:
virtual void DrawFrame();
virtual void DrawAnimationStep();
virtual void DrawGauge();
virtual void DrawOriginArea();
virtual void DrawProgressArea();
virtual void DrawRemainderArea();
virtual Boolean GetOriginFrame(Rect* originFrame);
virtual Boolean GetProgressFrame(Rect* progressFrame);
virtual Boolean GetRemainderFrame(Rect* remainderFrame);
virtual void GetRangeFrame(SInt32 startValue, SInt32 endValue, Rect* rangeFrame);
enum { kProgressHeight = 14 };
enum { kProgressImageHeight = 10, kProgressImageWidth = 16 };
enum { k1BitPattern, kDeepPattern, kNumProgressPatterns };
enum { kNumProgressAnimationSteps = 4 }; // 2, 4, 8, or 16 will work
enum { kAnimationDelay = 5 };
SInt32 mMinimum;
SInt32 mMaximum;
SInt32 mValue;
SInt32 mOriginValue; // usually == mMinimum
UInt32 mAnimationIndex;
SInt32 mLastAnimationTime; // used for quantized animation
static SInt8 kIndeterminateProgressImage[kNumProgressPatterns]
[kProgressImageHeight]
[kProgressImageWidth];
static AGAOffscreenImage* mgOffscreenIndeterminateProgressImage[kNumProgressPatterns];
};
#pragma mark AGASeparator
//
// AGASeparator ---------------------------------------------------------------
//
// AGASeparator implements the standard AGA separator line.
// It automatically determines its orientation based on the coordinate
// bounding box dimensions.
//
class AGASeparator : public AGAObject
{
public:
AGASeparator(Rect* bounds);
virtual ~AGASeparator();
virtual void DrawObject();
};
#pragma mark AGAGroupBox
//
// AGAGroupBox ---------------------------------------------------------------
//
// AGAGroupBox implements the standard AGA group box. A group box can
// either be primary or secondary. Secondary group boxes should be used
// inside primary group boxes, sez the AGA spec. You can supply a title
// string for the group box, or you can specify a "gap" width that is to
// be left blank to make room for a control or title string that will
// be drawn elsewhere.
//
class AGAGroupBox : public AGAObject
{
public:
enum { kPrimaryGroupBox = true, kSecondaryGroupBox = false };
AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType);
AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType, SInt16 titleGap);
AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType, StringPtr titleString);
AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType, SInt16 titleStringListResourceID, SInt16 titleStringIndex);
virtual ~AGAGroupBox();
virtual void SetTitleGap(SInt16 titleGap);
virtual void SetTitle(StringPtr newTitle, Boolean redraw);
virtual void DrawObject();
protected:
virtual void DrawPrimaryFrame(SInt16 topIndent, SInt16 gapSize);
virtual void DrawSecondaryFrame(SInt16 topIndent, SInt16 gapSize);
Boolean mIsPrimaryBox;
SInt16 mTitleGap; // horizontal gap for other object in title, no top indent
Str255 mTitle; // zero-length string indicates no title, no top indent
AGATextStyle mTextStyle;
};
#pragma mark AGATabPanel
//
// AGATabPanel ---------------------------------------------------------------
//
// AGATabPanel implements an AGA tab panels control.
//
// You can specify the location of the tabs (top or bottom, left or right).
// (Only "top" tabs are currently implemented!!! Other values do NOT work yet.)
// You can specify whether the whole tab panel frame is drawn, or whether just
// the tabs themselves are drawn, which allows you to attach tabs to something
// that you are drawing yourself. The simple constructor decides this based on
// the object bounds: if it's too small, there's no frame.
//
typedef struct
{
StringHandle mLabel;
SInt32 mTabWidth;
Boolean mDisabled;
void* mUserData; // used by adapter classes for pane/view pointer
} TabInfo, *TabInfoPtr, **TabInfoHandle;
class AGATabPanel : public AGAObject
{
public:
enum TabSize { kSmallTabs, kLargeTabs };
enum TabsLocation { kTopTabs, kBottomTabs, kLeftTabs, kRightTabs };
enum TabWidthKind { kVariableTabWidth, kCommonTabWidth }; // AGA spec is kVariableTabWidth
enum { kDontShrink = false, kShrinkToFit = true }; // for SetNumTabs shrinkToFit
static OSErr AllocateTabImages();
static void DisposeTabImages();
AGATabPanel(Rect* bounds, SInt32 initialTabIndex, const AGATextStyle& textStyle, SInt16 labelsID);
AGATabPanel(Rect* bounds, SInt32 initialTabIndex, const AGATextStyle& textStyle, SInt16 labelsID, TabWidthKind widthKind, TabsLocation location, Boolean drawFrame);
virtual ~AGATabPanel();
virtual void DrawObject();
virtual Boolean TrackMouse(Point mouseLocation);
virtual void SetObjectBounds(Rect* bounds, Boolean redraw);
virtual SInt32 GetCurrentTab();
virtual void SetCurrentTab(SInt32 tabIndex, Boolean redraw);
virtual SInt32 GetLastTabClicked();
virtual void SetTabSize(TabSize size); // specify large or small tabs
virtual void SetTabsLocation(TabsLocation location); // specify tabs location
virtual void SetTabsWidth(TabWidthKind widthKind); // specify tab vs. label width
virtual SInt16 GetTabHeight(); // get "height" of the tabs
virtual Boolean HasFrame(); // true if we will draw a frame
virtual void SetLabelsFromResource(SInt16 stringListResourceID); // creates 1 tab per string in the 'STR#'
virtual void SetNumTabs(SInt32 numLabels, Boolean shrinkToFit); // ensures space for n tabs, optionally removes excess
virtual SInt32 GetNumTabs(); // get number of tabs
virtual void SetTabLabel(SInt32 tabIndex, StringPtr itsLabel); // set one tab's label
virtual void GetTabLabel(SInt32 tabIndex, StringPtr itsLabel); // get one tab's label
virtual void SetTabEnable(SInt32 tabIndex, Boolean enable); // enable/disable one tab
virtual Boolean IsTabEnabled(SInt32 tabIndex); // get enable/disable state of one tab
virtual void SetTabUserData(SInt32 tabIndex, void* userData); // set extra data value for one tab; used by adapter classes for panel ptr
virtual void* GetTabUserData(SInt32 tabIndex); // get extra data value for one tab; used by adapter classes for panel ptr
virtual void CalculateTabWidths(); // recalc all tab widths using current labels
virtual void SetLabelsStyle(const AGATextStyle& textStyle); // set the text style for the labels
protected:
enum { kSmallTabImageHeight = 19, kSmallTabImageWidth = 12 };
enum { kLargeTabImageHeight = 24, kLargeTabImageWidth = 12 };
enum { kPanelEndMargin = 6 };
// AGAObject mouse tracking overrides.
virtual Boolean HitTest(Point mouseLocation);
virtual void SetTrackingState(Boolean isIn);
virtual void DrawBackground();
virtual void DrawFrame();
virtual void DrawTabs();
virtual void DrawFrameBox();
virtual void DrawFrameTop();
virtual void DrawOneTab(SInt32 tabIndex, Boolean pressed);
virtual void GetTabBounds(SInt32 tabIndex, Rect* tabBounds);
virtual void CalculateTabWidthsByKind(TabWidthKind widthKind);
virtual void CalculateTabSizeInfo();
virtual void AllocateTabInfo(SInt32 numTabs, Boolean shrinkToFit);
virtual void DisposeTabInfo();
virtual void CopyTabImage(UInt32 imageIndex, Point imageDestination, Boolean deep);
SInt32 mNumTabs;
SInt32 mCurrentTabIndex;
SInt32 mLastTabClicked;
TabInfoHandle mTabInfo; // handle to array of TabInfo
TabSize mTabSize; // small or large
TabsLocation mTabsLocation; // top, bottom, left, or right
TabWidthKind mTabWidthKind; // variable or same
Point mTabImageSize; // depends on mTabSize & mTabsLocation
Boolean mDrawFrame;
AGATextStyle mTextStyle;
// Drawing the tab contours manually is too tedious.
// So we use offscreen PixMap structures and blast them onto the screen.
// Current implementation doesn't use clip, so must be on an r2 background.
enum { kSmallTabImages, kLargeTabImages, kNumImageTypes };
enum { kTabNormalDeselectedL, kTabNormalDeselectedR,
kTabNormalSelectedL, kTabNormalSelectedR,
kTabPressedL, kTabPressedR,
kTabDisabledDeselectedL, kTabDisabledDeselectedR,
kTabDisabledSelectedL, kTabDisabledSelectedR,
kNumTabImages };
static SInt8 kSmallTabImageValues [kNumTabImages] [kSmallTabImageHeight] [kSmallTabImageWidth];
static SInt8 kLargeTabImageValues [kNumTabImages] [kLargeTabImageHeight] [kLargeTabImageWidth];
static SInt8 k1BitSmallTabImageValues [kNumTabImages] [kSmallTabImageHeight] [kSmallTabImageWidth];
static SInt8 k1BitLargeTabImageValues [kNumTabImages] [kLargeTabImageHeight] [kLargeTabImageWidth];
static AGAOffscreenImage* mgOffscreenTabImages [kNumTabImages] [kNumImageTypes];
static AGAOffscreenImage* mg1BitOffscreenTabImages [kNumTabImages] [kNumImageTypes];
};
#pragma mark GDIterator
//
// GDIterator -----------------------------------------------------
//
// To properly handle drawing in grayscale with multiple monitors
// and differing color depths, we must draw while iterating over
// the GD handles. This iterator makes a for loop easy while also
// reducing the clipping area to the appropriate device and setting
// a boolean to indicate whether the device is "deep" or not. "Deep"
// meaning suitable for grayscale drawing as opposed to black & white.
//
class GDIterator
{
public:
GDIterator();
virtual ~GDIterator();
void Setup(); // called by constructor; can be called again
Boolean More(Boolean& deep);// returns true while you should draw again
void Cleanup(); // called by destructor; can be called earlier
void ClipFurtherToCurrentDevice(); // can be called for tricky clipping situations (see slider labels)
protected:
// To look good in gray we need 4 bits in monochrome, or 8 bits in color.
// This is because 2 bits monochrome is only black, white, plus 2 shades;
// and 4 bits in color is just that plus 12 irrelevant colors.
enum { kDeepGrayscaleBits = 4, kDeepColorBits = 8 };
GDHandle FindNextValidDevice(GDHandle currentDevice, Boolean& deep);
void ClipFurtherToDevice(GDHandle aDevice);
Boolean mIteratedYet;
GDHandle mCurrentGDHandle; // inited by Setup, changed by More
static RgnHandle mSavedClipping; // saved by Setup, restored by Cleanup
};
#pragma mark AGAGroupsContainer
//
// AGAGroupsContainer --------------------------------------------------------
//
// This class is used internally to maintain the MExclusiveObject
// behavior that allows radio buttons to automatically maintain
// standard radio button group XOR behavior.
// It just maintains an array of AGAGroupMember structs, each of
// which identifies the group ID and contains a pointer to a
// group member.
// If you're using the adapter classes, this is not used.
//
typedef struct
{
UInt32 mGroupIDPart1;
UInt32 mGroupIDPart2;
MExclusiveObject* mGroupMember;
} AGAGroupMember;
class AGAGroupsContainer
#ifdef AGA_SUPERCLASS
: public AGA_SUPERCLASS
#endif // AGA_SUPERCLASS
{
public:
AGAGroupsContainer();
virtual ~AGAGroupsContainer();
void AGAAddGroupMember(MExclusiveObject* groupMember);
void AGARemoveGroupMember(MExclusiveObject* groupMember);
void AGAHitGroupMember(MExclusiveObject* groupMember);
protected:
void AddGroupMember(MExclusiveObject* groupMember, Boolean allowExpand);
void ExpandArray();
enum { kGroupArrayChunkSize = 16 };
UInt32 mGroupsArraySize;
AGAGroupMember** mGroups; // Handle to array of AGAGroupMember
};
#pragma mark AGA_Globals
//
// Global functions and variables -------------------------------------------
//
//
// These are the gAGARamp RGB color value indexes.
// They match the numbers specified in the AGA doc.
// rW is white.
// 1 thru 12 go from light gray to dark gray, matching AGA doc indexes.
// rA1 and rA2 are the additional dark grays referenced in the AGA doc.
// rB is black.
// rP1 thru rP4 are the purple shades for the disclosure triangle.
//
typedef enum
{
rW = 0,
r1 = 1,
r2 = 2,
r3 = 3,
r4 = 4,
r5 = 5,
r6 = 6,
r7 = 7,
r8 = 8,
r9 = 9,
r10 = 10,
r11 = 11,
r12 = 12,
rA1 = 13,
rA2 = 13,
rB = 15,
rP1 = 16,
rP2 = 17,
rP3 = 18,
rP4 = 19,
kNumRampColors,
OUT = -1
} RampIndex;
extern RGBColor gAGARamp[kNumRampColors];
extern Boolean gAGAHasColorQD;
extern const Str255 gGrayCouncilCopyright;
extern AGAGroupsContainer* gGroupsContainer;
extern UInt32 gAGADefaults;
// Turn default behavioral attributes off or on with these calls.
// These affect what default attributes are used for certain objects
// at the time they are instantiated, in the case where the attribute
// is not explicitly set as a constructor parameter or adapter class
// function.
extern void SetGrayCouncilDefault(UInt32 itemMask, Boolean turnOn);
extern Boolean TestGrayCouncilDefault(UInt32 itemMask);
// These are the attributes you can turn off or on with the above calls.
// They only affect new objects, not existing ones.
#define kAGALiveScrolling 0x00000001
#define kAGAProportionalScrolling 0x00000002
#define kAGALiveRSliders 0x00000004
#define kAGAProportionalRSliders 0x00000008
#define kAGALivePSliders 0x00000010
#define kAGAProportionalPSliders 0x00000020
// AGAStringOut is used by the AGA classes to draw their text.
#define kNoTruncation -1 // Toolbox defines smTruncEnd, smTruncMiddle, etc.
enum AGAStringOutColor { kNormalOutput, kDisabledOutput, kInverseOutput, kUseCurrentColor };
extern void AGAStringOut(StringPtr aString,
Rect* centeringFrame,
SInt32 truncation,
SInt32 justification,
AGAStringOutColor outColor,
Boolean deep,
const AGATextStyle& textStyle);
// AGATextBox is a replacement for TETextBox, with the same initial parameters, plus
// a couple of extra ones for AGA control over the text. This is used by AGAStaticText.
extern void AGATextBox(const void *textPtr,
SInt32 textLength,
const Rect *textFrame,
SInt16 justification,
AGAStringOutColor outColor,
Boolean deep,
const AGATextStyle& textStyle,
const RGBColor* teBackgroundColor);
// AGABackgroundPaint is used to paint window backgrounds.
enum AGABackgroundKind { kRaisedModelessBackground, kRaisedModalBackground, kFlatWindowBackground, kNoBackgroundPaint };
extern void AGABackgroundPaint(const Rect* backgroundBounds,
Boolean drawFill,
AGABackgroundKind backgroundKind,
Boolean isActive,
Boolean hasGrowBox);
// AGAInstallGrayWCTB is used to install gray r2 into the window's 'wctb' background.
extern OSErr AGAInstallGrayWCTB(WindowPtr aWindow);
// AGADrawBorderFrame is used to draw the "3D" sunken frame around an object.
// It supports correct dimming and "notched" shape (contoured to scroll bars).
extern void AGADrawBorderFrame(const Rect* bounds, Boolean isEnabled, Boolean isNotched, Boolean drawFrame, const RGBColor* windowBackgroundColor);
// AGAComputeTargetBorderRegion is used to build a region that defines the
// target border, aka "focus" frame.
// It supports "notched" shape (contoured to scroll bars).
extern void AGAComputeTargetBorderRegion(RgnHandle borderRegion, const Rect* bounds, Boolean isNotched);
// AGAClipFurther shrinks the clip region further from its current area
// to prevent drawing outside the specified rect.
extern void AGAClipFurther(Rect* clippingRect);
// AGA_PLstrcpy is a replacement for PLstrcpy so the plstringfuncs library is not needed.
// It's just a BlockMoveData call.
extern void AGA_PLstrcpy(StringPtr str1, ConstStr255Param str2);
// These background color determination routines are used by the adapter
// classes during instantiation of certain view types that must erase
// their background, and because tab panels vary the background color.
// See more comments where these are implemented.
enum { kInstallOnlyIfCustom = false, kInstallAlways = true }; // MacApp & PowerPlant need different behavior here
extern Boolean DetermineAGABackgroundColors(RGBColor* enabledColor, RGBColor* disabledColor, Boolean installIfNotCustom);
extern void InstallAGABackgroundColors(AGAObject* itsAGAObject, Boolean installIfNotCustom);
extern void TurnOnCustomAGABackgroundColors(RGBColor* enabledColor, RGBColor* disabledColor);
extern void TurnOffCustomAGABackgroundColors();
#endif // __GRAYCOUNCIL__